fix(env): stop an unreadable environment setting from picking a wrong default - #1880
fix(env): stop an unreadable environment setting from picking a wrong default#1880CaptainMittens wants to merge 1 commit into
Conversation
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
… default
atoi and atol answer 0 for text they cannot read, and 0 is a real setting at
three places in this project. So a typo, a trailing unit such as "30s", or a
stray space silently chose a value nobody asked for, and nothing on screen
said the setting had been dropped.
src/mcp/index_supervisor.c CBM_INDEX_WORKER_TIMEOUT_S
src/cli/hook_augment.c CBM_HOOK_DEADLINE_MS
src/mcp/mcp.c CBM_INDEX_MAX_RESTARTS
CBM_HOOK_DEADLINE_MS was the worst of the three. atoi answered 0, 0 is below
HA_DEADLINE_MIN_MS, and the clamp then handed back 50 ms -- the SHORTEST
deadline the setting allows, for a setting whose only purpose is to give the
hook more room. The comment above that function records a hunt for hook runs
that never finished, 0 of 24 real sessions, which is the exact symptom a
silently-shortened deadline produces.
CBM_INDEX_MAX_RESTARTS lost twice. A typo kept the default of 100, and
CBM_INDEX_MAX_RESTARTS=0 -- which reads as "do not restart" to anybody who
sets it -- also kept 100. The setting did the opposite of the request.
CBM_INDEX_WORKER_TIMEOUT_S fell through to the 15-minute default, so a test
set to give up after 30 seconds hung for 15 minutes with nothing to explain
why.
The fix adds one helper rather than three copies of the same check:
bool cbm_env_long(const char *name, long *out);
It answers true only when the variable is set, is not empty, and reads
cleanly from its first character to its last. It holds no policy -- no
minimum, no maximum, no default -- because the three sites disagree on all
three, and a helper that guessed would be wrong at two of them. The shape is
the one src/main.c:1104 already uses: an end pointer, errno, and a check that
nothing was left over. It also refuses a leading blank, which strtol would
otherwise step over, so " 5" is a slip rather than the number 5.
Each site keeps its own rule:
worker timeout an unreadable value keeps the 15-minute default AND logs
the value it dropped
restart cap 0 now means no restarts; an unreadable value keeps 100
AND logs the value it dropped
hook deadline an unreadable value now yields HA_DEADLINE_DEFAULT_MS,
not the floor. This one stays silent on purpose: the file
includes no log header and writes no stderr, because its
output is hook protocol.
The restart-cap parse was lifted out of a very large function into a named
index_restart_cap(), so it can be read and reached on its own.
Four tests come with the change. The two that pin the user-visible behaviour
were seen failing before the fix:
FAIL tests/test_cli.c:402: ms == 50, expected HOOK_DEADLINE_DEFAULT == 2000
(with "unreadable value \"abc\" gave 50 ms" printed above it)
FAIL tests/test_cli.c:434: cbm_index_restart_cap_for_testing() == 100,
expected 0 == 0
After the fix, TEST_SUITES="platform cli mcp" reports 518 passed, 2 failed.
The full suite reports 7635 passed, 2 failed. Both failures are in
tests/test_cli.c (lines 1826 and 6802), print "error: one or more agent
cleanup operations failed", and reproduce on a clean tree without this
change -- they depend on the coding agents installed on the machine.
make -f Makefile.cbm lint-ci passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
c9fd0a7 to
30dcb62
Compare
|
Same shape as #1922: an input the code cannot read becomes a plausible value, and nothing downstream can tell it from a real one. Here it is
This is one of four from a single scan for siblings of #1875's shape — #1875, #1877, #1880, #1881. Context for the set, and a question about the two still unfiled, is on #1877. |
|
Thank you for the detailed reproduce-first analysis and for keeping policy at the individual call sites instead of hiding it in the shared parser. This changes hook deadlines, worker timeout handling, and restart policy across the CLI and MCP paths, so we need more time to review compatibility and failure behavior before making a decision. No additional information is requested from you at this stage. |
What this fixes
atoiandatolanswer0for text they cannot read, and0is a realsetting at three places in this project. So a typo, a trailing unit such as
30s, or a stray space silently chose a value nobody asked for — and nothingon screen said the setting had been dropped.
src/cli/hook_augment.cCBM_HOOK_DEADLINE_MSsrc/mcp/mcp.cCBM_INDEX_MAX_RESTARTS=0src/mcp/index_supervisor.cCBM_INDEX_WORKER_TIMEOUT_S1.
CBM_HOOK_DEADLINE_MS— a typo bought the shortest possible deadlineatoianswers0,0is belowHA_DEADLINE_MIN_MS, and the clamp handedback 50 ms — for a setting whose only purpose is to give the hook more
room. The comment directly above that function records a hunt for hook runs
that never finished, 0 of 24 real sessions, which is the exact symptom a
silently-shortened deadline produces.
2.
CBM_INDEX_MAX_RESTARTS— the setting did the opposite of the requestTwo ways to lose. A typo kept the default of 100. And
CBM_INDEX_MAX_RESTARTS=0— which reads as "do not restart" to anybody whosets it — also kept 100.
3.
CBM_INDEX_WORKER_TIMEOUT_S— a 30-second test hung for 15 minutesThe comment above this override says it exists to tighten the timeout for
tests.
atolanswered0for30sor a stray space,0failed the> 0test, and the 15-minute default came back with nothing to explain it.
The fix
One helper, not three copies of the same check:
It answers true only when the variable is set, is not empty, and reads cleanly
from its first character to its last. It holds no policy — no minimum, no
maximum, no default — because the three sites disagree on all three, and a
helper that guessed would be wrong at two of them.
The shape is the one
src/main.c:1104already uses for--port=: an endpointer,
errno, and a check that nothing was left over. It adds one thing ontop — a refusal of a leading blank, because
strtolsteps over blanks of itsown accord, so
" 5"would otherwise read as the number 5. Theclisuitecaught that during this work.
Each site keeps its own rule:
0now means no restarts; unreadable keeps 100 AND logs the dropped valueHA_DEADLINE_DEFAULT_MS(2000), never the floorhook_augment.cstays silent on purpose: it includes no log header and writesno stderr, because its output is hook protocol.
The restart-cap parse was lifted out of a very large function into a named
index_restart_cap(), so it can be read and reached on its own.Tests
Four tests. The two that pin the user-visible behaviour were seen failing
before the fix:
Each carries a positive control first — a good value is still read — so a later
failure points at the unreadable case and not at a reader broken outright.
platform_env_long_reads_a_clean_numbertests/test_platform.cplatform_env_long_refuses_what_it_cannot_readtests/test_platform.ccli_hook_deadline_ignores_an_unreadable_valuetests/test_cli.ccli_index_restart_cap_honours_zero_and_refuses_junktests/test_cli.cTwo
_for_testingwrappers reach the statics, following the convention alreadyused 25 times in
src/cli/cli.h. The deadline wrapper is POSIX-only, matchingthe
#ifndef _WIN32block the function lives in.Checks run
make -f Makefile.cbm test-focused TEST_SUITES="platform cli mcp"518 passed, 2 failed, 6 skippedmake -f Makefile.cbm lint-ci=== CI linters passed ===— exit 0make -f Makefile.cbm cbmmake -f Makefile.cbm test7635 passed, 2 failed, 8 skippedThe two failures are in
tests/test_cli.c(lines 1826 and 6802), printerror: one or more agent cleanup operations failed, and reproduce on a cleantree without this change. They depend on the coding agents installed on the
machine.
How this was found
By scanning for siblings of the parse bug fixed in #1875 — "a parse reports
success while the input stays unread". #1877 fixed the confidence pair from the
same scan. This is the environment-variable group.
Checklist
git commit -s(DCO)make -f Makefile.cbm testrunmake -f Makefile.cbm lint-cirunFixes #1981